using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using MIMPGameLibrary;
using System.IO;
using System.Runtime.Serialization;

namespace MIMPWinForms.Forms
{
    public partial class MapSetupForm : Form
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        /// <summary>
        /// Occurs when a new game should be loaded from the GameState in the EventArgs.
        /// </summary>
        public event EventHandler<EventArgs<GameState>> LoadGame;

        protected virtual void RaiseLoadGame(GameState toLoad) {
            if (LoadGame != null) {
                if (log.IsInfoEnabled) log.Info("Raising LoadGame");
                LoadGame(this, new EventArgs<GameState>(toLoad));
            }
        }

        GameState selectedGameState;
        string mapDirectory;

        List<Panel> playerPanels;

        public MapSetupForm(string mapDirectory) {
            if (log.IsInfoEnabled) log.Info("Entered MapSetupForm constructor");
            InitializeComponent();
            playerPanels = new List<Panel>();
            playerPanels.Add(panelPlayer1);
            playerPanels.Add(panelPlayer2);
            playerPanels.Add(panelPlayer3);
            playerPanels.Add(panelPlayer4);
            playerPanels.Add(panelPlayer5);
            playerPanels.Add(panelPlayer6);
            playerPanels.Add(panelPlayer7);
            playerPanels.Add(panelPlayer8);

            if (log.IsDebugEnabled) log.Debug("Map directory is: " + mapDirectory);
            this.mapDirectory = mapDirectory;
            DirectoryInfo dir = new DirectoryInfo(mapDirectory);
            FileInfo[] maps = dir.GetFiles("*.mimp");
            if (log.IsDebugEnabled) log.Debug("Found " + maps.Length + " map files.");
            if (log.IsWarnEnabled && maps.Length == 0) log.Warn("No map files found!");
            foreach (FileInfo map in maps) {
                if (log.IsDebugEnabled) log.Debug("Adding map: " + map.Name);
                lstbxMaps.Items.Add(map.Name);
            }
            lstbxMaps.Select();
            if (log.IsInfoEnabled) log.Info("Exiting MapSetupForm constructor");
        }

        private void lstbxMaps_SelectedIndexChanged(object sender, EventArgs e) {
            if (lstbxMaps.SelectedItem == null) { return; }
            
            if (log.IsDebugEnabled) log.Debug("Entered lstbxMaps_SelectedIndexChanged");
            if (log.IsDebugEnabled) log.Debug("Selected map is: " + (string)lstbxMaps.SelectedItem);

            IFormatter loadformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            Stream loadStream = null;
            try {
                loadStream = new FileStream(mapDirectory + (string)lstbxMaps.SelectedItem, FileMode.Open, FileAccess.Read, FileShare.None);
            } catch (Exception ex) {
                if (log.IsErrorEnabled) log.Error("Error loading selected map", ex);
                MessageBox.Show("Error loading the selected map!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            selectedGameState = (GameState)loadformatter.Deserialize(loadStream);
            loadStream.Close();
            if (log.IsDebugEnabled) log.Debug("Deserialized game state.");

            txtArmySize.Text = "" + selectedGameState.Players[0].DeploymentPoints;
            txtCPCount.Text = "" + selectedGameState.ControlPointCount;
            txtCPToWin.Text = "" + selectedGameState.ControlPointCount;
            txtPlayerCount.Text = "" + selectedGameState.Players.Count;

            if (log.IsDebugEnabled) log.Debug("army size: " + txtArmySize.Text);
            if (log.IsDebugEnabled) log.Debug("control point count: " + txtCPCount.Text);
            if (log.IsDebugEnabled) log.Debug("control points to win: " + txtCPToWin.Text);
            if (log.IsDebugEnabled) log.Debug("player count: " + txtPlayerCount.Text);

            txtArmySize.Visible = true;
            txtCPCount.Visible = true;
            txtCPToWin.Visible = true;
            txtPlayerCount.Visible = true;

            btnStart.Enabled = true;

            for (int i = 0; i < playerPanels.Count; i++) {
                playerPanels[i].Enabled = i < selectedGameState.Players.Count;
                playerPanels[i].Controls[0].BackColor = playerPanels[i].Enabled ? Constants.XnaColorToSysColor(Constants.PLAYER_COLORS[i]) : SystemColors.Control;
                if (log.IsDebugEnabled) log.Debug("player " + i + " color: " + Constants.PLAYER_COLORS[i].ToString());
            }
            if (log.IsDebugEnabled) log.Debug("Exiting lstbxMaps_SelectedIndexChanged");
        }

        private void btnStart_Click(object sender, EventArgs e) {
            if (log.IsInfoEnabled) log.Info("Entered btnStart_Click");
            bool okToLoad = true;
            List<string> names = new List<string>();

            for (int i = 0; i < playerPanels.Count; i++) {
                if (playerPanels[i].Enabled && i < selectedGameState.Players.Count) {
                    string name = playerPanels[i].Controls[2].Text;
                    if (log.IsDebugEnabled) log.Debug("Validating player " + i + ": " + name);
                    if (String.IsNullOrEmpty(name)) {
                        if (log.IsDebugEnabled) log.Debug("Name was null or empty.");
                        MessageBox.Show("Please enter a name for player " + playerPanels[i].Controls[1].Text + ".");
                        okToLoad = false;
                        break;
                    } else if (names.Contains(name)) {
                        if (log.IsDebugEnabled) log.Debug("Name was a duplicate.");
                        MessageBox.Show("Two or more players have the same name.\nPlease enter a unique name for each player.");
                        okToLoad = false;
                        break;
                    } else {
                        names.Add(name);
                    }

                    selectedGameState.Players[i].Color = Constants.SysColorToXnaColor(playerPanels[i].Controls[0].BackColor);
                    selectedGameState.Players[i].Name = name;
                    if (log.IsDebugEnabled) log.Debug("Assigned color [" + selectedGameState.Players[i].Color.ToString() + "] to player " + selectedGameState.Players[i].Name);
                }
            }
            if (log.IsDebugEnabled) log.Debug("All names validated, loading game.");
            if (okToLoad) this.RaiseLoadGame(selectedGameState);
            if (log.IsInfoEnabled) log.Info("Exiting btnStart_Click");
        }
    }
}